package boot

import (
	"bufio"
	"bytes"
	"io"
	"reflect"
	"strings"
	"github.com/gogf/gf/os/gfile"
	"github.com/gogf/gf/os/genv"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/text/gregex"
)

var (
	ENV_FLIE       = ".env"
)

// 加载环境变量
func LoadEnv(m map[string]interface{}) {
	envData, _ := Decode([]byte(gfile.GetContents(ENV_FLIE)))
	for k, v := range m {
		switch v.(type) {
		case map[string]interface{}:
			LoadEnv(gconv.Map(v))
		case []interface{}:
			arr := gconv.Interfaces(v)
			for _, s := range arr {
				typeOfS := reflect.TypeOf(s)
				reflectKindS := typeOfS.Kind()
				switch reflectKindS {
				case reflect.Map:
					LoadEnv(gconv.Map(s))
				default:
					m[k] = GetEnv(v, envData)
				}
			}
		case string:
			m[k] = GetEnv(v, envData)
		default:
		}
	}
}

// 获取环境变量
func GetEnv(v interface{}, envData map[string]interface{}) (interface{}) {
	reg := `\$\{(.*?)\|\|(.*?)\}`
	subs, _ := gregex.MatchString(reg, gconv.String(v))
	if len(subs) != 0 {
		v = subs[2]
		if genv.Get(subs[1]) != "" {
			v = genv.Get(subs[1])
		}
		if envData[subs[1]] != nil {
			v = envData[subs[1]]
		}
	}
	return v
}

// Decode converts INI format to map.
func Decode(data []byte) (res map[string]interface{}, err error) {
	res = make(map[string]interface{})

	a := bytes.NewReader(data)
	r := bufio.NewReader(a)
	for {
		line, err := r.ReadString('\n')
		if err != nil {
			if line == "" {
				break
			}
			if err != io.EOF {
				return nil, err
			}
		}

		lineStr := strings.TrimSpace(string(line))
		if len(lineStr) == 0 {
			continue
		}

		if lineStr[0] == ';' || lineStr[0] == '#' {
			continue
		}

		if strings.Contains(lineStr, "=") {
			strIndex := strings.Index(lineStr, "=")
			values := strings.Split(lineStr, "=")
			res[strings.TrimSpace(values[0])] = strings.TrimSpace(lineStr[strIndex+1:])
		}
	}

	return res, nil
}
